<?php

namespace app\common\service;

use app\common\exception\Client;
use app\common\exception\Server;
use app\common\enum\ScopeEnum;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use app\common\model\User as UserModel;
use think\facade\Config;

class User
{
    /**
     * 微信小程序登录
     * @param $code
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getToken($code):array
    {
        // 获取微信用户信息
        $userInfo = $this->getWechatUserInfo($code);
        // 查询用户是否存在
        $user = UserModel::where('openid',$userInfo['openid'])->find();
        if (!$user) {
            //创建用户
            $user = userModel::create([
                'openid' => $userInfo['openid']
            ]);
        }

        // 生成JWT token
        $token = $this->generateToken($userInfo,$user->id);

        return ['token'=>$token];
    }

    /**
     * 准备jwt值
     * @param $wxResult
     * @param $uid
     * @return mixed
     */
    private function generateValue($wxResult, $uid)
    {
        $jwtValue = $wxResult;
        $jwtValue['uid'] = $uid;
        $jwtValue['scope'] = ScopeEnum::User;
        return $jwtValue;
    }

    /**
     * 生成JWT token
     * @param array $userInfo
     * @param int $user_id
     * @return string
     */
    private function generateToken(array $userInfo,int $user_id): string
    {
        $key = Config::get('jwt.key');
        $time = time();
        $payload = [
            'iss' => Config::get('jwt.iss'), // 签发者
            'aud' => Config::get('jwt.aud'), // 接收方
            'iat' => $time, // 签发时间
            'exp' => $time + 7200, // 过期时间
            'data' => $this->generateValue($userInfo, $user_id)
        ];

        return JWT::encode($payload, $key, 'HS256');
    }

    /**
     * 获取微信用户openid
     * @param string $code
     * @return array
     * @throws \Exception
     */
    public function getWechatUserInfo(string $code): array
    {

        $url = sprintf(Config::get('wechat.login_url'), Config::get('wechat.app_id'), Config::get('wechat.app_secret'), $code);
        $response = file_get_contents($url);
        $data = json_decode($response, true);

        if (empty($data)) {
            throw new Server($data['errmsg']);
        }
        return $data;
    }

    /**
     * 解析JWT Token获取用户ID
     * @param $token
     * @return int
     * @throws Client
     */
    public function getUserIdFromToken($token): int
    {
        // 去除Bearer前缀
        if (strpos($token, 'Bearer ') === 0)$token = substr($token, 7);
        try {
            $key = Config::get('jwt.key');
            $decoded = JWT::decode($token, new Key($key, 'HS256'));
            return $decoded->data->uid;
        } catch (Exception $e) {
            throw new Client(223001,$e->getMessage());
        }
    }


}